﻿package net.wangit.dev.table;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

import net.wangit.LabelUtil;
import net.wangit.context.ActionContext;
import net.wangit.context.ActionResult;
import net.wangit.dev.DomainAction;
import net.wangit.framework.config.DomainsSettings;
import net.wangit.jdbc.ColumnRow;
import net.wangit.jdbc.DB;
import net.wangit.jdbc.DBFactory;
import net.wangit.jdbc.DBImplementor;
import net.wangit.jdbc.QueryParameters;
import net.wangit.jdbc.Table;
import net.wangit.jdbc.database.Database;
import net.wangit.util.Checker;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class InputDatabaseTableAction extends DomainAction {

	private static final Log log = LogFactory
			.getLog(net.wangit.dev.table.InputDatabaseTableAction.class);

	public InputDatabaseTableAction() {
	}

	public void doAction(DB db, ActionContext ac) throws Exception {
		String tableName = ac
				.getRequestParameter("addtable.database.tablename");
		String datasource = ac
				.getRequestParameter("addtable.database.datasource");
		ActionResult result = ac.getActionResult();
		try {
			int count = input(db, datasource, tableName);
			result.addInfo(LabelUtil.get(ac, "dev", "table.input.1", Integer
					.toString(count)));
		} catch (Exception e) {
			log.error(e);
			result.setSuccessful(false);
			result.addError(LabelUtil
					.get(ac, "dev", "table.input.0", tableName));
			throw e;
		}
	}

	private int input(DB db, String datasource, String tableName)
			throws Exception {
		DBImplementor actionDB = null;
		if (Checker.isEmpty(datasource))
			actionDB = (DBImplementor) DBFactory.getDB(DomainsSettings
					.getDatasource(domain));
		else
			actionDB = (DBImplementor) DBFactory.getDB(datasource);
		QueryParameters qp = new QueryParameters();
		qp.setMaxRows(1);
		ResultSet rs = actionDB.getResultSet((new StringBuilder("select "))
				.append(tableName).append(".* from ").append(tableName)
				.toString(), qp);
		if (rs == null)
			return -1;
		List<String> pkNames = getPKNames(actionDB, tableName);
		Database database = actionDB.getJDBCSettings().getDatabase();
		Table table = new Table("dev", "TABLE");
		ColumnRow row = table.addInsertRow();
		row.set("t", tableName);
		db.save(table);
		ResultSetMetaData meta = rs.getMetaData();
		int columnCount = meta.getColumnCount();
		int resultCount = 0;
		table = new Table("dev", "COLUMN");
		for (int i = 1; i <= columnCount; i++) {
			String columnName = meta.getColumnName(i).toLowerCase();
			if (!"row_".equals(columnName)) {
				resultCount++;
				int sqlTypeCode = meta.getColumnType(i);
				String columnTypeName = meta.getColumnTypeName(i);
				int precision = 1;
				try {
					precision = meta.getPrecision(i);
				} catch (Exception e) {
					log.debug("precision too big!", e);
				}
				int scale = meta.getScale(i);
				int type = database.getTypeCode(sqlTypeCode, columnTypeName,
						precision, scale);
				int isNullable = meta.isNullable(i);
				row = table.addInsertRow();
				row.set("pk", pkNames.contains(columnName) ? "1" : "0");
				row.set("nn", isNullable != 0 ? "0" : "1");
				row.set("t", tableName);
				row.set("c", columnName);
				row.set("dt", type);
				row.set("cl", (new StringBuilder("[")).append(columnName)
						.append("]").toString());
				row.set("l", meta.getColumnDisplaySize(i));
				row.set("s", scale);
				row.set("o", i * 10);
				row.set("v", "1");
			}
		}

		db.save(table);
		return resultCount;
	}

	private List<String> getPKNames(DB db, String tableName) {
		List<String> list = new ArrayList<String>();
		try {
			DatabaseMetaData dbMeta = db.getConnection().getMetaData();
			ResultSet pkRSet = dbMeta.getPrimaryKeys(null, null, tableName);
			while (pkRSet.next()) {
				list.add(((String) pkRSet.getObject(4)).toLowerCase());
			}
		} catch (Exception e) {
			log.error("find PrimaryKeys error:", e);
		}
		return list;
	}

}
